using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace OpenComposite.Base.Designer
{
	public class ConnectedSymbol : Symbol
	{
		#region Initialization
		public ConnectedSymbol()
		{
			init();
		}
		private void init()
		{
			this.BeginUpdate();

			_connectorDefaultEnd = new RectangleConnector();
			_connectorDefaultStart = new EllipseConnector();

			_connectorsTop = new List<Connector>();
			_connectorsBottom = new List<Connector>();
			_connectorsLeft = new List<Connector>();
			_connectorsRight = new List<Connector>();

			this.EndUpdate();
		}
		#endregion

		#region Public Members

		#region Properties
		
		public Connector DefaultStartConnector
		{
			get { return _connectorDefaultEnd; }
			set
			{
				if ( _connectorDefaultEnd != value ) {
					_connectorDefaultEnd = value;
					doConnectorDefaultEndChanged();
				}
			}
		}
		public Connector DefaultEndConnector
		{
			get { return _connectorDefaultStart; }
			set
			{
				if ( _connectorDefaultStart != value ) {
					_connectorDefaultStart = value;
					doConnectorDefaultStartChanged();
				}
			}
		}

		#endregion

		#region Events
		#endregion

		#region Methods

		public virtual void AddConnector(RouteDockDirection dock, Connector connector)
		{
			int dx = 5, dy = 5;
			switch ( dock ) {
				case RouteDockDirection.Top:
					connector.Location = new Point(
						dx + ( ( connector.Width + dx ) * this.TopConnectors.Count ),
						- (int)( connector.Height / 2 ) - dy);
					connector.Anchor = System.Windows.Forms.AnchorStyles.Top |
									   System.Windows.Forms.AnchorStyles.Left;
					this.TopConnectors.Add(connector);
					break;
				case RouteDockDirection.Bottom:
					connector.Location = new Point(
						dx + ( ( connector.Width + dx ) * this.BottomConnectors.Count ),
						this.Height - (int)( connector.Height / 2 ) - dy);
					connector.Anchor = System.Windows.Forms.AnchorStyles.Bottom |
									   System.Windows.Forms.AnchorStyles.Left;
					this.BottomConnectors.Add(connector);
					break;
				case RouteDockDirection.Right:
					connector.Location = new Point(
						this.Width - (int)( connector.Width / 2 ) - dx,
						dy + ( ( connector.Height + dy ) * this.RightConnectors.Count ));
					connector.Anchor = System.Windows.Forms.AnchorStyles.Top |
									   System.Windows.Forms.AnchorStyles.Right;
					this.RightConnectors.Add(connector);
					break;
				case RouteDockDirection.Left:
					connector.Location = new Point(
						- (int)( connector.Width / 2 ) - dx,
						dy + ( ( connector.Height + dy ) * this.LeftConnectors.Count ));
					connector.Anchor = System.Windows.Forms.AnchorStyles.Top |
									   System.Windows.Forms.AnchorStyles.Left;
					this.LeftConnectors.Add(connector);
					break;
			}
			this.Controls.Add(connector);
		}

		#region Override
		
		public override bool CreateRouteStart(DesignerControl controlEnd,
			out IConnector connector, out LineCap cap, out CustomLineCap customcap,
			out RouteDockDirection dockStart, out RouteDockDirection dockEnd, out bool useStartConnectorAsRouteStart)
		{
			bool ok = base.CreateRouteStart(controlEnd, out connector, out cap, out customcap,
											out dockStart, out dockEnd, out useStartConnectorAsRouteStart);

			Connector c = GetStartConnector(controlEnd);
			dockStart = GetStartDockDirection(controlEnd, dockStart);
			AddConnector(dockStart, c);
			connector = c;
			useStartConnectorAsRouteStart = false;

			return ok;
		}
		public override bool CreateRouteEnd(DesignerControl controlStart,
			out IConnector connector, out LineCap cap, out CustomLineCap customcap,
			out RouteDockDirection dockStart, out RouteDockDirection dockEnd, out bool useEndConnectorAsRouteEnd)
		{
			bool ok = base.CreateRouteEnd(controlStart, out connector, out cap, out customcap,
										  out dockStart, out dockEnd, out useEndConnectorAsRouteEnd);

			Connector c = GetEndConnector(controlStart);
			dockEnd = GetEndDockDirection(controlStart, dockEnd);
			AddConnector(dockEnd, c);
			connector = c;
			useEndConnectorAsRouteEnd = false;

			return ok;
		}

		#endregion

		#endregion

		#endregion

		#region Protected Members

		#region Properties
		protected List<Connector> TopConnectors
		{
			get { return _connectorsTop; }
		}
		protected List<Connector> BottomConnectors
		{
			get { return _connectorsBottom; }
		}
		protected List<Connector> LeftConnectors
		{
			get { return _connectorsLeft; }
		}
		protected List<Connector> RightConnectors
		{
			get { return _connectorsRight; }
		}
		#endregion

		#region Methods
		protected virtual RouteDockDirection GetStartDockDirection(
			DesignerControl controlEnd, RouteDockDirection defaultDock)
		{
			return defaultDock;
		}
		protected virtual RouteDockDirection GetEndDockDirection(
			DesignerControl controlStart, RouteDockDirection defaultDock)
		{
			return defaultDock;
		}
		protected virtual Connector GetStartConnector(DesignerControl controlEnd)
		{
			Connector c = this.DefaultEndConnector.GetType()
				.GetConstructor(Type.EmptyTypes).Invoke(new object[0]) as Connector;
			return c;
		}
		protected virtual Connector GetEndConnector(DesignerControl controlStart)
		{
			Connector c = this.DefaultStartConnector.GetType()
				.GetConstructor(Type.EmptyTypes).Invoke(new object[0]) as Connector;
			return c;
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables
		List<Connector> _connectorsTop;
		List<Connector> _connectorsBottom;
		List<Connector> _connectorsLeft;
		List<Connector> _connectorsRight;

		Connector _connectorDefaultEnd;
		Connector _connectorDefaultStart;
		#endregion

		#region Methods

		private void doConnectorDefaultEndChanged()
		{
			this.Repaint();
		}
		private void doConnectorDefaultStartChanged()
		{
			this.Repaint();
		}

		#endregion

		#region Event Handlers
		#endregion

		#endregion
	}
}
